import _ from 'lodash'
import moment from 'moment'
import { getMetrics } from '@/utils/study.js'

/**
 * 将数字格式化为两位数字字符串，不足两位在前面补0
 * @param {number} n - 要格式化的数字
 * @returns {string} 格式化后的两位数字字符串
 */
export const formattedNumber = (n) => {
  return n.toString().padStart(2, '0')
}

/**
 * 获取多个数组中最大的长度
 * @param {...Array} arrays - 要比较的数组列表
 * @returns {number} 最大的数组长度
 */
export const getMaxArrayLength = (...arrays) => {
  // 使用 map 获取所有数组的长度，然后用 Math.max 求出最大值
  return Math.max(...arrays.map((array) => array.length))
}

/**
 * 根据数字获取所在分组的所有数字
 * @param {number|string} num - 要查找的数字
 * @param {Array<Array<number>>} groups - 分组数组
 * @returns {Array<number>} 返回数字所在分组的所有数字，如果未找到分组则返回空数组
 */
export const getGroupNumbers = (num, groups) => {
  const groupIndex = _.findIndex(groups, (group) => _.includes(group, _.toNumber(num)))
  return groupIndex !== -1 ? groups[groupIndex] : []
}

export const copyTextToClipboard = (dataToCopy) => {
  navigator.clipboard
    .writeText(dataToCopy)
    .then(() => {
      // 可以在这里添加任何成功复制后的操作，比如提示用户
      // console.log("已复制到剪贴板: " + dataToCopy);
    })
    .catch(() => {
      // console.error('Failed to copy text: ', err);
    })
}

/**
 * 在二维数组中查找值，返回子数组在外部数组中的索引值
 * @param {Array<Array<any>>} array 二维数组
 * @param {any} value 要查找的值
 * @returns {number} 子数组的索引值，找不到则返回 -1
 */
export const findValueIndexIn2DArray = (array, value) => {
  if (!Array.isArray(array)) {
    throw new Error('输入的第一个参数必须是一个二维数组')
  }

  for (let i = 0; i < array.length; i++) {
    if (array[i].includes(value)) {
      return i // 返回子数组的索引
    }
  }

  return -1 // 如果找不到值，返回 -1
}

/**
 * 随机打乱数组，不修改原数组
 * @param {Array<any>} array 要打乱的数组
 * @returns {Array<any>} 随机打乱的新数组
 */
export const shuffleArray = (array) => {
  if (!Array.isArray(array)) {
    throw new Error('输入的参数必须是一个数组')
  }

  // 创建数组的副本
  const shuffledArray = [...array]

  // 使用 Fisher-Yates 洗牌算法
  for (let i = shuffledArray.length - 1; i > 0; i--) {
    const randomIndex = Math.floor(Math.random() * (i + 1))
    ;[shuffledArray[i], shuffledArray[randomIndex]] = [shuffledArray[randomIndex], shuffledArray[i]]
  }

  return shuffledArray
}

/**
 * 在二维数组中查找值所在的子数组
 * @param {Array<Array<any>>} array 二维数组
 * @param {any} value 要查找的值
 * @returns {Array<any> | null} 找到则返回子数组，未找到返回 null
 */
export const findSubArray = (array, value) => {
  if (!Array.isArray(array)) {
    throw new Error('输入的第一个参数必须是一个二维数组')
  }

  for (const subArray of array) {
    if (subArray.includes(value)) {
      return subArray // 找到并返回子数组
    }
  }

  return null // 如果未找到，返回 null
}

/**
 * 计算理论出现次数
 * @param {number} totalPeriods 总期数
 * @param {number} totalNumbers 总号码数
 * @param {number} groupSize 每组号码数
 * @returns {object} 单个号码的理论出现次数和分组的理论出现次数
 */
export const calculateTheoreticalOccurrences = (totalPeriods, groupSize) => {
  return ((totalPeriods / 49) * groupSize).toFixed(2)
}

/**
 * 处理 allValues 和 selectGroupMap，返回处理后的结果
 *
 * @param {Array} allValues - 包含所有值的数组，每个元素应包含 `number` 属性
 * @param {Object} selectGroupMap - 选择的组映射
 * @returns {Array} 处理后的结果数组
 */
export function getSeriesForLineTypeThree(allValues, selectGroupMap) {
  // console.log('selectGroupMap', selectGroupMap)
  return _.chain(allValues)
    .cloneDeep()
    .map((element, index) => {
      const currentNumber = _.toNumber(element.number)
      const prevNumber = index > 0 ? _.toNumber(allValues[index - 1].number) : null

      // 计算 currentValue
      const currentValue = _.chain(selectGroupMap)
        .values()
        .map((groupArray) => {
          const prevGroup = prevNumber ? _.find(groupArray, (group) => _.includes(group, prevNumber)) || [] : []
          return _.includes(prevGroup, currentNumber)
        })
        .every((isAccurate) => !isAccurate) // 如果所有值都是 false，则 currentValue 为 10，否则为 0
        .thru((allFalse) => (allFalse ? 10 : 0))
        .value()

      // 计算 allGroupAccuracy
      const allGroupAccuracy = _.chain(selectGroupMap)
        .mapValues((groupArray) => {
          const groupsNumber = _.find(groupArray, (group) => _.includes(group, currentNumber)) || []
          const prevGroupsNumber = prevNumber ? _.find(groupArray, (group) => _.includes(group, prevNumber)) || [] : []
          return {
            currentGroupAccuracy: !prevGroupsNumber.includes(currentNumber),
            groupsNumber,
            prevGroupsNumber
          }
        })
        .map((accuracy, groupsName) => ({ groupsName, ...accuracy }))
        .value()

      return {
        value: currentValue,
        sourceData: element,
        allGroupAccuracy,
        itemStyle: { color: currentValue === 0 ? '#ee6666' : '#91cc75' }
      }
    })
    .thru((mappedValues) => {
      // console.log('mappedValues', mappedValues)
      const { maxCorrectStreak, maxWrongStreak } = getMaxStreak(mappedValues)

      // 统计 value 出现的次数
      const valueCount = _.countBy(mappedValues, 'value')
      // console.log('valueCount', valueCount)

      return mappedValues.map((e) => ({
        ...e,
        valueCount,
        maxCorrectStreak,
        maxWrongStreak
      }))
    })
    .value()
}

/**
 * 处理 `allValues` 和 `selectGroupMap`，返回处理后的结果
 *
 * @param {Array} allValues - 包含所有值的数组，每个元素应包含 `number` 属性
 * @param {Object} selectGroupMap - 选择的组映射，每个组包含一个数字数组
 * @returns {Array} 处理后的结果数组
 */
export const getSeriesForLineTypeTwo = (_allValues, _groups) => {
  // console.log('_groups', _groups)
  const allValues = _.chain(_allValues)
    .cloneDeep()
    .map((element, index) => {
      // 获取当前数字所在的分组
      const groupsNumber = getGroupNumbers(element.number, _groups)
      // 获取前一期数字所在的分组，如果是第一期则返回空数组
      const prevGroupsNumber = index > 0 ? getGroupNumbers(_.get(_allValues, [index - 1, 'number']), _groups) : []
      /**
       * 计算当前值:
       * - 第一期固定为10分
       * - 其他期: 如果当前数字在前一期分组中出现则为0分(杀号正确),否则为10分(杀号错误)
       */
      let currentValue

      if (index === 0 || !prevGroupsNumber.includes(_.toNumber(element.number))) {
        currentValue = 10
      } else {
        currentValue = 0
      }
      return {
        value: currentValue,
        sourceData: element,
        groupsNumber,
        prevGroupsNumber,
        itemStyle: { color: currentValue === 0 ? '#ee6666' : '#91cc75' }
      }
    })
    .thru((mappedValues) => {
      // 统计 value 出现的次数
      const valueCount = _.countBy(mappedValues, 'value')

      const { maxCorrectStreak, maxWrongStreak } = getMaxStreak(mappedValues)
      // const demo05_result = demo05(mappedValues.map((e) => e.value))
      // console.log('demo05_result', demo05_result)
      return mappedValues.map((e) => ({
        ...e,
        valueCount,
        maxCorrectStreak,
        maxWrongStreak
        // demo05_result
      }))
    })
    .value()
  return allValues
}

/**
 * 处理 `allValues` 和 `selectGroupMap`，返回处理后的结果
 *
 * @param {Array} allValues - 包含所有值的数组，每个元素应包含 `number` 属性
 * @param {Object} selectGroupMap - 选择的组映射，每个组包含一个数字数组
 * @param {Object} options - 指标选项
 * @returns {Array} 处理后的结果数组
 */
export const getSeriesForLineTypeTwoWithMetrics = (_allValues, _groups, options) => {
  // console.log('_groups', _groups)
  const allValues = _.chain(_allValues)
    .cloneDeep()
    .map((element, index) => {
      // 获取当前数字所在的分组
      const groupsNumber = getGroupNumbers(element.number, _groups)
      // 获取前一期数字所在的分组，如果是第一期则返回空数组
      const prevGroupsNumber = index > 0 ? getGroupNumbers(_.get(_allValues, [index - 1, 'number']), _groups) : []
      /**
       * 计算当前值:
       * - 第一期固定为10分
       * - 其他期: 如果当前数字在前一期分组中出现则为0分(杀号正确),否则为10分(杀号错误)
       */
      let currentValue

      if (index === 0 || !prevGroupsNumber.includes(_.toNumber(element.number))) {
        currentValue = 10
      } else {
        currentValue = 0
      }
      return {
        value: currentValue,
        sourceData: element,
        groupsNumber,
        prevGroupsNumber,
        itemStyle: { color: currentValue === 0 ? '#ee6666' : '#91cc75' }
      }
    })
    .thru((mappedValues) => {
      return mappedValues.map((e, i) => {
        const tempValues = _.chain(mappedValues)
          .cloneDeep()
          .slice(0, i + 1)
          .map((item) => item.value)
          .value()
        const metrics = getMetrics(tempValues, options)
        return {
          ...e,
          metrics
        }
      })
    })
    .thru((mappedValues) => {
      // 统计 value 出现的次数
      const valueCount = _.countBy(mappedValues, 'value')

      const { maxCorrectStreak, maxWrongStreak } = getMaxStreak(mappedValues)

      return mappedValues.map((e) => ({
        ...e,
        valueCount,
        maxCorrectStreak,
        maxWrongStreak
        // demo05_result
      }))
    })
    .value()
  return allValues
}

/**
 * 处理 `allValues` 和 `selectValue`，返回处理后的结果
 *
 * @param {Array} allValues - 包含所有值的数组，每个元素应包含 `number` 属性
 * @param {number} selectValue - 选择的值
 * @returns {Array} 处理后的结果数组
 */
export const getSeriesForPast = (_allValues, _selectValue) => {
  const values = _allValues

  // 使用一个对象来跟踪每个数字最后一次出现的位置
  const lastAppearances = {}

  const result = _allValues.map((item, index) => {
    const number = item.number
    let repeatInterval = lastAppearances[number] !== undefined ? index - lastAppearances[number] : -1

    lastAppearances[number] = index // 更新该数字最后一次出现的位置

    // console.log(repeatInterval)
    // console.log(_selectValue)

    // 如果重复间隔大于20，则设置为0
    if (repeatInterval >= _selectValue + 1) {
      repeatInterval = -1
    }

    // 维护最近的_selectValue个数据项数组
    const recentValues = values.slice(Math.max(0, index - _selectValue), index).map((v) => v.number)

    return {
      value: repeatInterval,
      sourceData: item,
      recentValues: recentValues
      // itemStyle: Number(item.number) === 25 ? { color: "#FF0000" } : {}, // 为值为 25 的点设置颜色
    }
  })
  return result
}

/* eslint-disable */
export const getMoneyText = (data, title) => {
  return `
	${title}：
		${data
      .map((item) => {
        return `
        ${item.router}
        kill ${item.last.groupsNumber.length}    最大错误次数：${item.maxCountError}    正确率：${item.accuracyRate}%
        [
          ${item.last.groupsNumber.join(',')}
        ]
      `
      })
      .join('\n')}
`
}

// 获取所有尾号
export const getMantissa = (n) => {
  // 将数字转换为个位数
  const mantissa = parseInt(n) % 10
  // 生成1-49的数组，过滤出尾数相同的数字，并格式化为两位数字符串
  return _.range(1, 50)
    .filter((num) => num % 10 === mantissa)
    .map((num) => (num < 10 ? `0${num}` : `${num}`))
}

// 获取剩余号码
export const getRemainingNumbers = (excluded) => {
  // 1-49的号码
  const allNumbers = Array.from({ length: 49 }, (_, i) => i + 1)

  // 处理被减去的号码：去重并统一格式（数字）
  const excludedSet = new Set(
    excluded.map((item) => {
      // 处理字符串（如 '06'），统一转为数字
      return typeof item === 'string' ? parseInt(item, 10) : item
    })
  )

  // 过滤掉被排除的号码
  const remainingNumbers = allNumbers.filter((num) => !excludedSet.has(num))

  // 格式化结果：保证小于10的数字补0
  const formattedNumbers = remainingNumbers.map((num) => (num < 10 ? `0${num}` : `${num}`))

  return formattedNumbers
}

// 获取差值号码
export const getDifferenceNumbers = (minuend, subtrahend) => {
  // 1-49的号码
  const allNumbers = minuend.map((item) => {
    return typeof item === 'string' ? parseInt(item, 10) : item
  })

  // 处理被减去的号码：去重并统一格式（数字）
  const excludedSet = new Set(
    subtrahend.map((item) => {
      // 处理字符串（如 '06'），统一转为数字
      return typeof item === 'string' ? parseInt(item, 10) : item
    })
  )

  // 过滤掉被排除的号码
  const remainingNumbers = allNumbers.filter((num) => !excludedSet.has(num))

  // 格式化结果：保证小于10的数字补0
  const formattedNumbers = remainingNumbers.map((num) => (num < 10 ? `0${num}` : `${num}`))

  return formattedNumbers
}

// 获取最近365期数据
export const getRecentData = (data, count = 1365) => {
  return data.slice(-count)
}

// 获取去重的年份数组
export const getYears = (data) => {
  // 使用 Map 或 Set 去重年份
  const years = [...new Set(data.map((item) => item.time.split('-')[0]))]
  return years
}

// 获取最大连续错误次数和最大连续正确次数
export const getMaxStreak = (mappedValues) => {
  // 计算连续正确和错误的最大次数
  let currentStreak = 1
  let maxCorrectStreak = 0
  let maxWrongStreak = 0
  let prevValue = mappedValues[0]?.value || 10

  for (let i = 1; i < mappedValues.length; i++) {
    if (mappedValues[i].value === prevValue) {
      currentStreak++
    } else {
      if (prevValue === 10) {
        // 正确
        maxCorrectStreak = Math.max(maxCorrectStreak, currentStreak)
      } else {
        // 错误
        maxWrongStreak = Math.max(maxWrongStreak, currentStreak)
      }
      currentStreak = 1
    }
    prevValue = mappedValues[i].value
  }

  // 处理最后一个streak
  if (prevValue === 10) {
    maxCorrectStreak = Math.max(maxCorrectStreak, currentStreak)
  } else {
    maxWrongStreak = Math.max(maxWrongStreak, currentStreak)
  }
  return {
    maxCorrectStreak,
    maxWrongStreak
  }
}

/**
 * 计算准确率
 * @param {number[]} valueCount - 值的计数数组
 * @returns {number} - 计算后的准确率
 */
export const calculateAccuracy = (valueCount) => {
  const correct = BigInt(valueCount[10] || 0)
  const total = BigInt(valueCount[0] || 0) + correct

  // 如果总数为 0，返回 0
  if (total === 0n) return 0

  // 计算准确率，并转换回普通数字
  const accuracy = (correct * 100n) / total // 使用 BigInt 计算百分比
  return Number(accuracy) // 转换回普通数字并返回
}

// 获取下期日期
export const getMacauNextDay = (time) => {
  return moment(time).add(1, 'days').format('YYYY-MM-DD')
}

// 获取香港下一期
export const getHongKongNextDay = async () => {
  const fetchWithFallback = async (url, fallbackUrl) => {
    try {
      const response = await fetch(url)
      // console.log('response', response)
      if (!response.ok) throw new Error('Failed to fetch primary URL')
      const { data } = await response.json()
      return moment(data.six.next.awardTime, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD')
    } catch (error) {
      const fallbackResponse = await fetch(fallbackUrl)
      if (!fallbackResponse.ok) throw new Error('Failed to fetch fallback URL')
      const { data } = await fallbackResponse.json()
      return moment(data.six.next.awardTime, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD')
    }
  }

  return fetchWithFallback('//hk-marksix.com/111api/lottery/info/six', '//marksixlottery.net/api/lottery/info/six')
}

/**
 * 找出当前最大的 groupName 和其关联的文件日期的方法
 * @param {Array} tableData - 表格数据数组
 * @returns {Object} 包含最大 groupName、最大数字部分和文件日期的对象
 */
export const getMaxGroupNameWithDate = (tableData) => {
  // 使用 Lodash 找到最大值
  const maxGroup = _.maxBy(tableData, (item) => {
    const match = item.groupName.match(/FIVE_RANGE_(\d+)_GROUPS/)
    return match ? parseInt(match[1], 10) : -1 // 提取数字并转为整数
  })

  if (maxGroup) {
    const maxNumberMatch = maxGroup.groupName.match(/FIVE_RANGE_(\d+)_GROUPS/)
    const dateMatch = maxGroup.fileName.match(/^(\d{4}-\d{2}-\d{2})/)

    return {
      groupName: maxGroup.groupName,
      maxNumber: maxNumberMatch ? parseInt(maxNumberMatch[1], 10) : null,
      date: dateMatch ? dateMatch[1] : null // 提取文件名中的日期部分
    }
  }

  return null // 如果没有有效的 groupName
}

// 获取预测结果
export const getPredictionResults = (data) => {
  // todo 表格需要计算出哪些列?
  // 1. 是否预测正确
  // 2. 杀掉的组(组的相关属性)
  // 3. 杀掉的号码(号码的相关属性)
  // 4. 预测的号码(号码的相关属性)
  // 5. 本次预测的准确率
  // 6. 本次预测的平均连续正确次数
  // 7. 本次预测的平均连续错误次数
  // 8. 段数

  const result = data.map((item, index) => {
    let map_item = {
      ...item,
      // 是否预测正确
      isAccurate: true,
      // 杀掉的组
      killGroups: [],
      // 杀掉的号码
      killNumbers: [],
      // 预测的号码
      predictNumbers: [],
      // 准确率
      accuracy: 0
    }

    // 每次从0截取到当前index
    const currentData = data.slice(0, index + 1)
    // 包含当期数据
    // console.log(currentData)

    if (item === 0) {
    }

    return map_item
  })

  return result

  // 处理数据
  // const result = data.map((item, index) => {
  //   // 每次从0截取到当前index
  //   const currentData = data.slice(0, index+1)

  //   // 初始化所有号码的计数为 0，并确保键是 "01" 到 "49" 的格式
  //   const allNumbersCount = _.chain(_.range(1, 50))
  //     .map((number) => [_.padStart(number.toString(), 2, '0'), 0])
  //     .fromPairs()
  //     .value()

  //   // 统计每个号码出现的次数
  //   const numberCount = _.countBy(currentData, 'number')

  //   // 将实际计数与初始化的计数合并，未出现的号码将保持计数为 0
  //   _.assign(allNumbersCount, numberCount)

  //   // 是否开始统计热号
  //   const isStart = _.chain(allNumbersCount)
  //     .filter((value, key) => value > 1)
  //     .size()
  //     .gt(24)
  //     .value()

  //   // 转换 allNumbersCount 为数组并降序排序
  //   const sortedNumbers = _(allNumbersCount)
  //     .map((count, number) => ({ number, count })) // 转换为对象数组
  //     .orderBy(['count'], ['desc']) // 根据 count 降序排序
  //     .value()

  //   // 热号
  //   let hotNumbers = []
  //   // 冷号
  //   let coldNumbers = []

  //   if (isStart) {
  //     hotNumbers = sortedNumbers.slice(0, 25).map((item) => item.number)
  //     coldNumbers = sortedNumbers.slice(25).map((item) => item.number)
  //   }

  //   return {
  //     ...item,
  //     hotNumbers,
  //     coldNumbers,
  //     allNumbersCount,
  //     sortedNumbers
  //   }
  // })
}

// 判断生成的结果中是否包含空数组
export const hasEmptyArray = (generatedGroups) => {
  // 遍历生成的分组对象
  for (const key in generatedGroups) {
    // 检查每个分组的长度
    if (Array.isArray(generatedGroups[key]) && generatedGroups[key].length === 0) {
      // 如果有空数组，返回 true
      return true
    }
  }
  // 如果没有空数组，返回 false
  return false
}

// 生成路由
export const generateRangeRoutes = (folderPrefix, folderString, RangeLineView, hidden = true) => {
  const RANGE_LIST = Array.from({ length: 1500 }, (_, i) => `range-${String(i + 1).padStart(8, '0')}`)

  return RANGE_LIST.map((item) => {
    // 'range-001' -> 'Range001'
    const nameStr = item
      .split('-')
      .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
      .join('')

    // 'range-001' -> 'range 001'
    const titleStr = item.replace('-', ' ')

    // 'range-001' -> 'RANGE_001'
    const groupsKeyStr = item.toUpperCase().replace('-', '_')

    return {
      path: item,
      component: RangeLineView,
      name: folderString + nameStr,
      meta: {
        title: titleStr,
        noCache: true,
        groupsKey: folderPrefix + groupsKeyStr + '_GROUPS'
      },
      hidden
      // todo cyan: task 随机路由默认隐藏
      // hidden: true // 默认false
    }
  })
}
